﻿using System;

namespace Games.DigitalSame
{
    class Game
    {
        private int[,] status;
        private int[,] history;
        private int[,] clicks;

        public void Init(int width, int height)
        {
            this.width = width;
            this.height = height;
            this.status = new int[width, height];
            this.history = new int[width, height];
            this.clicks = new int[width, height];
            this.IsFinished = false;

            var random = new Random(DateTime.Now.Millisecond);
            for(int x = 0; x < width; x++)
            {
                for(int y = 0; y < height; y++)
                {
                    var delta = random.Next(9);
                    if(delta > 0)
                    {
                        this.Change(x, y, delta);
                        this.Change(x + 1, y, delta);
                        this.Change(x, y + 1, delta);
                        this.Change(x - 1, y, delta);
                        this.Change(x, y - 1, delta);
                    }
                    this.history[x, y] = delta;
                }
            }
        }

        public void Reload()
        {
            this.status = new int[width, height];
            this.clicks = new int[width, height];
            this.IsFinished = false;
            for(int x = 0; x < width; x++)
            {
                for(int y = 0; y < height; y++)
                {
                    var delta = this.history[x, y];
                    if(delta > 0)
                    {
                        this.Change(x, y, delta);
                        this.Change(x + 1, y, delta);
                        this.Change(x, y + 1, delta);
                        this.Change(x - 1, y, delta);
                        this.Change(x, y - 1, delta);
                    }
                }
            }
        }

        public void Click(int x, int y)
        {
            this.clicks[x, y]++;
            this.Change(x, y);
            this.Change(x + 1, y);
            this.Change(x, y + 1);
            this.Change(x - 1, y);
            this.Change(x, y - 1);
            this.Check();
        }
        public bool InBoard(int x, int y)
        {
            if(x < 0 || x >= width)
            {
                return false;
            }
            if(y < 0 || y >= height)
            {
                return false;
            }
            return true;
        }
        private void Change(int x, int y, int addvalue = 1)
        {
            if(InBoard(x, y))
            {
                var val = status[x, y] + addvalue;
                if(val > 9)
                    status[x, y] = val % 9;
                else
                    status[x, y] = val;
            }
        }

        public int GetValue(int x, int y)
        {
            return status[x, y];
        }
        public int GetClick(int x, int y)
        {
            return history[x, y];
        }

        private int width;
        private int height;

        private void CalaClick()
        {
            this.ClickCount = 0;
            this.AllClickCount = 0;
            for(int x = 0; x < width; x++)
            {
                for(int y = 0; y < height; y++)
                {
                    this.ClickCount += this.clicks[x, y] % 9;
                    this.AllClickCount += this.clicks[x, y];
                }
            }
        }
        public int ClickCount { get; private set; }
        public int AllClickCount { get; private set; }

        private void Check()
        {
            this.IsFinished = false;
            int? val = null;
            for(int i = 0; i < width; i++)
            {
                for(int j = 0; j < height; j++)
                {
                    if(val == null)
                    {
                        val = status[i, j];
                    }
                    else if(val != status[i, j])
                    {
                        return;
                    }
                }
            }
            this.IsFinished = true;
            this.CalaClick();
        }

        public bool IsFinished { get; private set; }
    }
}
